sample\
10 sample_shooting.hsp
#include "hsp3dish.as"
#include "mod_layerbutton.hsp"
#packopt xsize 480
#packopt ysize 800
; バーチャルパッド用サンプル シューティング(480x800)
screen 0,480,800
title "バーチャルパッド用サンプル シューティング"
randomize
// HSP3Dish.js用データフォルダ設定
info_os = sysinfo(0)
if instr(info_os,0,"Emscripten")>=0 : mm_dir="" : else : mm_dir="data/"
// 画像読み込み
celload mm_dir+"pad.png", -1
cel_pad = stat : celdiv cel_pad,128,128, 64,64
celload mm_dir+"nub.png", -1
cel_nub = stat : celdiv cel_nub,64,64, 32,32
celload mm_dir+"btn.png", -1
cel_btn = stat : celdiv cel_btn,64,64
celload mm_dir+"btn2x.png", -1
cel_btn2x = stat : celdiv cel_btn2x,128,128
celload mm_dir+"bean.png", -1
cel_bean = stat : celdiv cel_bean,64,42, 32,21
pxConL = 100 ; コントローラ表示位置の中心X座標
pyConL = ginfo_sy-100 ; コントローラ表示位置の中心Y座標
szConL = 1.0 ; コントローラのサイズ倍率
zurizuri = 1 ; スティックを範囲外まで動かしたら本体を追従させるオプション (逆方向に操作する際、常に一定のスライド量で反対側まで操作できます)
gosub *create_analogCon ; アナログスティック作成
pxConR = ginfo_sx-60
pyConR = ginfo_sy-70
szConR = 1.0
gosub *create_btnCon ; ボタン作成
// 自機
px=240.0: py=600.0: pspeed=5: life=3: bomb=1: hit_flash=0 : analogx=0.0 : analogy=0.0
// 敵管理
e_num=20: dim ex,e_num: dim ey,e_num: dim evx,e_num: dim evy,e_num: dim et,e_num: dim ealive,e_num
// 弾管理
s_num=20: dim sx,s_num: dim sy,s_num: dim salive,s_num
// メインループ
*mainloop
redraw 0: color 0,0,0: boxf: font msgothic,20
frame++
if keyM { ; メニューボタン
if gameOver == 0 {
gamePause = 1 - gamePause
}else {
// ゲームリスタート
px=240.0: py=600.0: pspeed=5: life=3: bomb=1: hit_flash=0 : analogx=0.0 : analogy=0.0
e_num=20: dim ex,e_num: dim ey,e_num: dim evx,e_num: dim evy,e_num: dim et,e_num: dim ealive,e_num // 弾管理
s_num=20: dim sx,s_num: dim sy,s_num: dim salive,s_num
frame=1: score=0: item_y=0: gameOver=0
}
}
// ポーズまたはゲームオーバー中は操作/更新を停止
if gamePause == 0 && gameOver == 0 {
// アナログスティック入力
px = limitf(px+(analogx*10),8,ginfo_sx-8)
py = limitf(py+(analogy*10),8,ginfo_sy-8)
if keyA { ; 弾追加
repeat s_num
if salive(cnt) : continue
sx(cnt)=px
sy(cnt)=py
salive(cnt)=1
break
loop
}
if keyB && bomb==1 && bomb_active==0 {
bomb_active=1
bomb_radius=0
bomb=0
}
// 敵更新
repeat e_num
if ealive(cnt) == 0 {
ex(cnt)=rnd(440)+20
ey(cnt)=-rnd(500)-8
evx(cnt)=rnd(10)-5
evy(cnt)=2+rnd(2+frame/600)
et(cnt)=0
ealive(cnt)=1
}
et(cnt)++
ex(cnt)+=evx(cnt)
ey(cnt)+=evy(cnt)
ex(cnt)+=sin(0.1*et(cnt))*2
if ex(cnt)>488 || ex(cnt)<-8 : evx(cnt)=-evx(cnt)
if ey(cnt)>808 : ealive(cnt)=0
loop
// 弾更新
repeat s_num
if salive(cnt) == 0 : continue
sy(cnt)-=8
if sy(cnt)<0 : salive(cnt)=0
loop
// ボムアイテム生成
if frame\1200 == 0 : item_x=rnd(440)+20: item_y=1
if item_y {
item_y+=2
color 255,255,0: boxf item_x,item_y,item_x+16,item_y+16
if abs(px-item_x)<16 && abs(py-item_y)<16 : bomb=1: item_y=0
}
// 当たり判定
repeat e_num
if ealive(cnt) == 0 : continue
// 自機と敵
if abs(px-ex(cnt))<16 && abs(py-ey(cnt))<16 && hit_flash==0 {
life--
hit_flash=30 ; 点滅カウント
ealive(cnt)=0
if life<=0 : gameOver=1
}
cnt2=cnt
// 弾と敵
repeat s_num
if salive(cnt) == 0 : continue
if abs(ex(cnt2)-sx(cnt))<10 && abs(ey(cnt2)-sy(cnt))<12 {
ealive(cnt2)=0
salive(cnt)=0
score+=10
}
loop
loop
// ボム処理
if bomb_active {
bomb_radius+=16
color 255,255,255: boxf px-bomb_radius,py-bomb_radius,px+bomb_radius,py+bomb_radius
repeat e_num : ealive(cnt)=0 : loop
if bomb_radius>800 : bomb_active=0
}
}
// 自機表示
if hit_flash : hit_flash--
if hit_flash\4 == 0 { ; 点滅考慮
color 0,255,255: boxf px-8,py-8,px+8,py+8
}
// 敵表示
repeat e_num
if ealive(cnt) == 0 : continue
color 255,0,0: boxf ex(cnt)-8,ey(cnt)-8,ex(cnt)+8,ey(cnt)+8
loop
// 弾表示
repeat s_num
if salive(cnt) == 0 : continue
color 255,255,0: boxf sx(cnt)-2,sy(cnt)-4,sx(cnt)+2,sy(cnt)+4
loop
// ポーズ/ゲームオーバー 表示
if gamePause || gameOver {
gmode 3,,,200
ax=0,ginfo_sx,ginfo_sx,0
ay=0,0,ginfo_sy,ginfo_sy
color: gsquare -1,ax,ay
if gameOver == 0 {
if pausemx == 0 : pausemx=-ginfo_sx ; 初回は画面外に飛ばす (描画幅計測)
pos (ginfo_sx-pausemx)/2,350
color 255,255: mes "Pause"
if pausemx<0 : pausemx=ginfo_mesx
}else {
if gmov1mx == 0 : gmov1mx=-ginfo_sx ; 初回は画面外に飛ばす (描画幅計測)
if gmov2mx == 0 : gmov2mx=-ginfo_sx ;
font msgothic,30,1
pos (ginfo_sx-gmov1mx)/2,350
color 255: mes "Game Over"
if gmov1mx<0 : gmov1mx=ginfo_mesx
font msgothic,20
if frame\80>20 {
pos (ginfo_sx-gmov2mx)/2,450
color 255,255: mes "Restart : Push Menu Button!"
if gmov2mx<0 : gmov2mx=ginfo_mesx
}
}
}
// スコア/残機/ボム 表示
color 255,255,255
pos 10,10: mes "SCORE:"+score
pos 10,30: mes "LIFE:"+life
pos 10,50: mes "BOMB:"+bomb+"/1"
redraw 1
await 16
goto *mainloop
// アナログスティック作成
*create_analogCon
pos pxConL-(szConL*64), pyConL-(szConL*64)
layerbutton szConL*128,szConL*128, 0,0 {
laybtn_settings 0,4,1+4 ; 設定 : ボタン外からスライドしてもクリック + ボタンを押しても消さない
laybtn_hitarea -1, objlayer_size_x/2,objlayer_size_y/2, objlayer_size_x ; 円形ヒットエリア
if lparam == objlayer_cmddraw {
if layerbtn_clickx!=-1 && layerbtn_clicky!=-1 { ; クリック/タッチ中
layerbtn_clickx_ = double(layerbtn_clickx) + zrzrx
layerbtn_clicky_ = double(layerbtn_clicky) + zrzry
rr = double(objlayer_size_x)/2 ; スティックが動く範囲の半径
dx = -layerbtn_clickx_ + layerbtn_mousex
dy = -layerbtn_clicky_ + layerbtn_mousey
_dist = dx*dx + dy*dy
if _dist > rr*rr {
dist = sqrt(_dist)
layerbtn_mousex_ = double(dx * rr) / dist + layerbtn_clickx_
layerbtn_mousey_ = double(dy * rr) / dist + layerbtn_clicky_
if zurizuri : zrzrx-=layerbtn_mousex_-layerbtn_mousex : zrzry-=layerbtn_mousey_-layerbtn_mousey
}else{
layerbtn_mousex_ = double(layerbtn_mousex)
layerbtn_mousey_ = double(layerbtn_mousey)
}
// パッドのアナログ値
analogx = (layerbtn_mousex_ - (layerbtn_clickx_))*2 / objlayer_size_x
analogy = (layerbtn_mousey_ - (layerbtn_clicky_))*2 / objlayer_size_y
// 表示用の補正
layerbtn_mousex_ -= objlayer_size_x/2
layerbtn_mousey_ -= objlayer_size_y/2
layerbtn_clickx_ -= objlayer_size_x/2
layerbtn_clicky_ -= objlayer_size_y/2
}else {
zrzrx=0.0 : zrzry=0.0
analogx=0.0 : analogy=0.0
// 表示用の補正
layerbtn_mousex_ = 0.0
layerbtn_mousey_ = 0.0
layerbtn_clickx_ = layerbtn_mousex_
layerbtn_clicky_ = layerbtn_mousey_
}
// pad, nub 描画
laybtn_ezcel cel_pad, 1,,,,,,, layerbtn_clickx_, layerbtn_clicky_, szConL,szConL ; ezcelの裏技 : 第9引数から ボタン画像ずらし量, 強制倍率 を指定できる
laybtn_ezcel cel_nub, 1,,,,,,, layerbtn_mousex_, layerbtn_mousey_, szConL,szConL
}
return
}
return
// ボタン作成
*create_btnCon
; A (shot)
pos pxConR-(szConR*48), pyConR-(szConR*48)
layerbutton szConR*96,szConR*96, 0,1 {
laybtn_settings 0,4+8,1+4 ; 設定 : 同グループ押下中ならボタン外からスライドしてもクリック + ボタンを押しても消さない
laybtn_hitarea -1, objlayer_size_x/2,objlayer_size_y/2, objlayer_size_x ; 円形ヒットエリア
if lparam == objlayer_cmddraw {
font msgothic,24,1 : color 200,200,200
laybtn_ezcel cel_btn2x,0, "Shot"
if gamePause : return
keyA = ( (layerbtn_stat & LAYBTN_PRESS_IN)!=0 && layerbtn_cnt == 0 )
}
return
}
; B (bomb)
pos pxConR-(szConR*120), pyConR-(szConR*16)
layerbutton szConR*64,szConR*64, 1,1 {
laybtn_settings 0,4+8,1+4 ; 設定 : 同グループ押下中ならボタン外からスライドしてもクリック + ボタンを押しても消さない
laybtn_hitarea -1, objlayer_size_x/2,objlayer_size_y/2, objlayer_size_x ; 円形ヒットエリア
if lparam == objlayer_cmddraw {
font msgothic,16,1 : color 200,200,200
laybtn_ezcel cel_btn,0, "Bomb"
if gamePause : return
keyB = ( (layerbtn_stat & LAYBTN_PRESS_IN)!=0 && layerbtn_cnt == 0 )
}
return
}
; menu
pos pxConR+(szConR*-5), pyConR-(szConR*90)
layerbutton szConR*64,szConR*42, 2,1 {
laybtn_settings 0,2,1+4 ; 設定 : マウスクリックで即決定 + ボタンを押しても消さない
laybtn_hitarea -3, objlayer_size_x/2,objlayer_size_y/2, objlayer_size_x,objlayer_size_y, 20.0/180.0*M_PI ; 長方形(角度付き)ヒットエリア
if lparam == objlayer_cmddraw {
font msgothic,20 : color 200,200,200
pos objlayer_axis_x+objlayer_size_x/2, objlayer_axis_y+objlayer_size_y/2
switch (layerbtn_stat|1^1) ; _SELECTED状態を除去して分岐 [(layerbtn_stat & $FFFE)でもOK]
case LAYBTN_FOCUS_IN : id_celdiv = 1 : swbreak
case LAYBTN_PRESS_IN : id_celdiv = 2 : swbreak
default : id_celdiv = 0
swend
celput cel_bean, id_celdiv, szConR,szConR, 20.0/180.0*M_PI
laybtn_mes "≡",0, 1,1
keyM = ( layerbtn_stat == LAYBTN_PRESS_IN_SELECTED )
}
return
}
return